package com.ruoyi.stock2.thread;

import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.stock2.domain.ForetellResult;
import com.ruoyi.stock2.domain.PriceCompAverage200;
import com.ruoyi.stock2.domain.TRADEDATA;
import com.ruoyi.stock2.domain.TRADEDATA200;
import com.ruoyi.stock2.mapper.DownTradedataScheduleMapper;
import com.ruoyi.stock2.mapper.PriceCompAverage200Mapper;
import com.ruoyi.stock2.service.IForetellResultService;
import com.ruoyi.stock2.service.ITRADEDATA200Service;
import com.ruoyi.stock2.service.ITRADEDATAService;
import com.ruoyi.stock2.utils.DateUtils2;
import com.ruoyi.stock2.utils.OtherUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

//生成预测文本 调用模型预测 生成图片
public class BuildSeq2SeqPredTextThreadNew implements Runnable {

    private static final Logger log = LoggerFactory.getLogger(BuildSeq2SeqPredTextThreadNew.class);

    ITRADEDATA200Service itradedata200Service;

    PriceCompAverage200Mapper priceCompAverage200Mapper;

    DownTradedataScheduleMapper downLoadTradedataScheduleMapper;

    private String pred_text_dir;

    private String seq2seqstockPred_main_dir;

    Map map1 = new HashMap(5000);

    Map map7 = new HashMap(5000);

    private boolean working = false;

    public boolean isWorking() {
        return working;
    }

    public void setWorking(boolean working) {
        this.working = working;
    }


    //单例实现 涉及到任务状态
    public static BuildSeq2SeqPredTextThreadNew getInstance() {
        return Singtonle.instance;
    }

    private static class Singtonle {
        private static BuildSeq2SeqPredTextThreadNew instance = new BuildSeq2SeqPredTextThreadNew();
    }

    @Override
    public void run() {
        working = true;
        itradedata200Service = (ITRADEDATA200Service) SpringUtils.getBean(ITRADEDATA200Service.class);
        downLoadTradedataScheduleMapper = (DownTradedataScheduleMapper) SpringUtils.getBean(DownTradedataScheduleMapper.class);
        priceCompAverage200Mapper = (PriceCompAverage200Mapper) SpringUtils.getBean(PriceCompAverage200Mapper.class);

        pred_text_dir = downLoadTradedataScheduleMapper.selectDownTradedataScheduleByName("pred_text_dir").getValue();
        seq2seqstockPred_main_dir = downLoadTradedataScheduleMapper.selectDownTradedataScheduleByName("seq2seqstockPred_main_dir").getValue();


        productTextType1();
        productTextType7();

        working = false;
    }


    public void productTextType1() {

        map1 = getSetType1Num();
        List<PriceCompAverage200> list1 = priceCompAverage200Mapper.selectBuyTrainByType();
        log.warn("selectBuyTrainByType1:" + list1.size());

        String predir = pred_text_dir + "seq2seq_pred/seq2seq_type1_pre.txt";
        File file = new File(predir);
        BufferedWriter writer = null;
        try {
            if (!file.exists()) {
                file.createNewFile();
            } else {
                file.delete();
                file.createNewFile();
            }
            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, false), "utf-8"));

            for (int i = 0; i < list1.size(); i++) {
                writer.write(getStrType1(list1.get(i)) + "\r\n");
                writer.flush();
            }
            writer.flush();
        } catch (IOException e1) {
            e1.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
                if (list1.size() > 0) {
                    OtherUtils.exec("python " + seq2seqstockPred_main_dir + "AttentionWrapperType1.py");
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }


        }


    }


    public String getStrType1(PriceCompAverage200 priceCompAverage200) {
        StringBuilder stringBuilderIt = new StringBuilder();
        TRADEDATA200 tradedata = new TRADEDATA200();
        tradedata.setSymbol(priceCompAverage200.getSymbol());
        tradedata.setDatetime(priceCompAverage200.getF1date());
        List<TRADEDATA200> listinput = itradedata200Service.selectTradedataInput40Days(tradedata);
        List<TRADEDATA200> listtarget = itradedata200Service.selectTradedataTarget40Days(tradedata);

        stringBuilderIt.append(listinput.get(0).getSymbol()).append(",");
        stringBuilderIt.append(DateUtils2.formatDateToString(listinput.get(0).getDatetime(), "yyyy-MM-dd")).append(",");

        List<BigDecimal> lista = new ArrayList<BigDecimal>();
        for (TRADEDATA200 tradedata1 : listinput) {
            lista.add(tradedata1.getCloseprice());
        }
        for (TRADEDATA200 tradedata1 : listtarget) {
            lista.add(tradedata1.getCloseprice());
        }
        BigDecimal min = Collections.min(lista);

        for (int j = listinput.size() - 1; j > 0; j--) {
            BigDecimal bigDecimal = listinput.get(j).getCloseprice().divide(min, 3, BigDecimal.ROUND_HALF_UP);

            if (map1.get(String.valueOf(bigDecimal)) == null && bigDecimal.compareTo(new BigDecimal(27.584)) < 0) {
                while (map1.get(String.valueOf(bigDecimal)) == null && bigDecimal.compareTo(new BigDecimal(27.584)) < 0) {
                    bigDecimal = bigDecimal.add(new BigDecimal(0.001)).setScale(3, BigDecimal.ROUND_HALF_UP);
                }
            } else if (map1.get(String.valueOf(bigDecimal)) == null && bigDecimal.compareTo(new BigDecimal(27.584)) > 0) {
                bigDecimal = new BigDecimal(27.584);
            }

            stringBuilderIt.append(bigDecimal).append(" ");
        }
        stringBuilderIt.append(listinput.get(0).getCloseprice().divide(min, 3, BigDecimal.ROUND_HALF_UP));
        stringBuilderIt.append(",").append(stringBuilderIt);

        return stringBuilderIt.toString();
    }


    public Map<String, Integer> getSetType1Num() {
        String setdir = pred_text_dir + "seq2seq_train/seq2seq_type1_train_Set.txt";
        Path path = Paths.get(setdir);
        Charset charset = Charset.forName("utf-8");
        try (BufferedReader reader = Files.newBufferedReader(path, charset)) {
            String line = null;
            while ((line = reader.readLine()) != null) {
                String[] spline = line.split(" ");
                for (String str : spline) {
                    map1.put(str, 1);
                }
            }
        } catch (IOException x) {
            System.err.format("IOException: %s%n", x);
        }
        return map1;
    }

    public void productTextType7() {
        List<PriceCompAverage200> list7 = priceCompAverage200Mapper.selectBuyTrainByType7();
        log.warn("selectBuyTrainByType7:" + list7.size());
        map7 = getSetType7Num();

        String predir = pred_text_dir + "seq2seq_pred/seq2seq_type7_pre.txt";
        File file = new File(predir);
        BufferedWriter writer = null;
        try {
            if (!file.exists()) {
                file.createNewFile();
            } else {
                file.delete();
                file.createNewFile();
            }
            writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, false), "utf-8"));

            for (int i = 0; i < list7.size(); i++) {
                writer.write(getStrType7(list7.get(i)) + "\r\n");
                writer.flush();
            }

            writer.flush();
        } catch (IOException e1) {
            e1.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
                if (list7.size() > 0) {
                    OtherUtils.exec("python " + seq2seqstockPred_main_dir + "AttentionWrapperType7.py");
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    public String getStrType7(PriceCompAverage200 priceCompAverage200) {
        StringBuilder stringBuilderIt = new StringBuilder();
        TRADEDATA200 tradedata = new TRADEDATA200();
        tradedata.setSymbol(priceCompAverage200.getSymbol());
        tradedata.setDatetime(priceCompAverage200.getF1date());
        List<TRADEDATA200> listinput = itradedata200Service.selectTradedataInput40Days(tradedata);
        List<TRADEDATA200> listtarget = itradedata200Service.selectTradedataTarget40Days(tradedata);

        stringBuilderIt.append(listinput.get(0).getSymbol()).append(",");
        stringBuilderIt.append(DateUtils2.formatDateToString(listinput.get(0).getDatetime(), "yyyy-MM-dd")).append(",");

        List<BigDecimal> lista = new ArrayList<BigDecimal>();
        for (TRADEDATA200 tradedata1 : listinput) {
            lista.add(tradedata1.getCloseprice());
        }
        for (TRADEDATA200 tradedata1 : listtarget) {
            lista.add(tradedata1.getCloseprice());
        }
        BigDecimal min = Collections.min(lista);

        for (int j = listinput.size() - 1; j > 0; j--) {
            BigDecimal bigDecimal = listinput.get(j).getCloseprice().divide(min, 3, BigDecimal.ROUND_HALF_UP);

            if (map7.get(String.valueOf(bigDecimal)) == null && bigDecimal.compareTo(new BigDecimal(12.024)) < 0) {
                while (map7.get(String.valueOf(bigDecimal)) == null && bigDecimal.compareTo(new BigDecimal(12.024)) < 0) {
                    bigDecimal = bigDecimal.add(new BigDecimal(0.001)).setScale(3, BigDecimal.ROUND_HALF_UP);
                }
            } else if (map7.get(String.valueOf(bigDecimal)) == null && bigDecimal.compareTo(new BigDecimal(12.024)) > 0) {
                bigDecimal = new BigDecimal(12.024);
            }

            stringBuilderIt.append(bigDecimal).append(" ");
        }
        stringBuilderIt.append(listinput.get(0).getCloseprice().divide(min, 3, BigDecimal.ROUND_HALF_UP));
        stringBuilderIt.append(",").append(stringBuilderIt);

        return stringBuilderIt.toString();
    }


    public Map<String, Integer> getSetType7Num() {
        String setdir = pred_text_dir + "seq2seq_train/seq2seq_type7_train_Set.txt";
        Path path = Paths.get(setdir);
        Charset charset = Charset.forName("utf-8");
        try (BufferedReader reader = Files.newBufferedReader(path, charset)) {
            String line = null;
            while ((line = reader.readLine()) != null) {
                String[] spline = line.split(" ");
                for (String str : spline) {
                    map7.put(str, 1);
                }
            }
        } catch (IOException x) {
            System.err.format("IOException: %s%n", x);
        }
        return map7;
    }

}
